package pers.vic.boot.security.data.interceptor;

import java.lang.reflect.Field;

import org.apache.ibatis.mapping.BoundSql;

import pers.vic.boot.security.data.enums.RowDataHandlerType;
import pers.vic.boot.security.data.model.DataRowAuthColumn;
import pers.vic.boot.security.data.model.DataRowAuthModel;
import pers.vic.boot.security.jwt.AuthorityInfo;

/**
 * 
 *  @description: 数据权限拦截器的基类
 *  @author Vic.xu
 *  @date: 2020年5月18日下午4:41:27
 */
public abstract class AuthorityMethod {

	/**
	 * 当前线程中需要拦截的权限字段数据
	 */
	protected static final ThreadLocal<DataRowAuthModel> LOCAL_AUTHORITY_DATA = new ThreadLocal<DataRowAuthModel>();
	
	/**
	 * 当前线程中保存的用户权限信息AuthorityInfo
	 */
	protected static final ThreadLocal<AuthorityInfo> LOCAL_AUTHORITY_INFO = new ThreadLocal<AuthorityInfo>();
	
	/**
	 * 设置权限相关数据: 理应在jwtFilter#login的时候
	 * @param into
	 */
	public static void setAuthrityInfo(AuthorityInfo into) {
		LOCAL_AUTHORITY_INFO.set(into);
	}
	
	/**
	 * 用于权限拦截的时候使用
	 * @return
	 */
	public static AuthorityInfo getAuthrityInfo() {
		return LOCAL_AUTHORITY_INFO.get();
	}
	
	/**
	 * 清除线程中的用户权限信息,注意主动调用
	 * @param into
	 */
	public static void removeAuthrityInfo(AuthorityInfo into) {
		LOCAL_AUTHORITY_INFO.remove();
	} 

	/**
	 * 设置 AuthorityData 参数
	 *
	 * @param AuthorityData
	 */
	protected static void setLocalAuthorityData(DataRowAuthModel authorityData) {
		LOCAL_AUTHORITY_DATA.set(authorityData);
	}

	/**
	 * 获取 AuthorityData 参数
	 *
	 * @return
	 */
	public static DataRowAuthModel getLocalAuthorityData() {
		return LOCAL_AUTHORITY_DATA.get();
	}

	/**
	 * 移除本地变量
	 */
	public static void clearAuthorityData() {
		LOCAL_AUTHORITY_DATA.remove();
	}

	/**
	 * 业务代码设置过滤条件
	 * 
	 * @param type   数据行权限过滤类型
	 * @param column SQL 中需要过滤的字段 如a.dept_id
	 */
	public static void start(RowDataHandlerType type, String column) {
		DataRowAuthModel data = getLocalAuthorityData();
		if (data == null) {
			data = new DataRowAuthModel();
		}
		DataRowAuthColumn filterColumn = new DataRowAuthColumn(type, column);
		data.addFilterColumn(filterColumn);
		setLocalAuthorityData(data);
	}

	/**
	 * 用处理后的SQL覆盖原始SQL
	 * 
	 * 通过反射把SQL设置回去
	 */
	public void overrideSql(BoundSql boundSql, String sql) {
		try {
			Field field = boundSql.getClass().getDeclaredField("sql");
			field.setAccessible(true);
			field.set(boundSql, sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
